package com.vueblog.webapi.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vueblog.webapi.entity.BlogEntity;
import com.vueblog.webapi.entity.BlogTagsEntity;
import com.vueblog.webapi.entity.TypeEntity;
import com.vueblog.webapi.entity.UserEntity;
import com.vueblog.webapi.enums.ResponseEnum;
import com.vueblog.webapi.exception.BusinessException;
import com.vueblog.webapi.mapper.BlogMapper;
import com.vueblog.webapi.mapper.BlogTagsMapper;
import com.vueblog.webapi.request.BasePageRequest;
import com.vueblog.webapi.request.CreateOrUpdateBlogRequest;
import com.vueblog.webapi.request.GetBlogInfoByWordRequest;
import com.vueblog.webapi.request.GetBlogInfoPageRequest;
import com.vueblog.webapi.response.ArchiveBlogResponse;
import com.vueblog.webapi.response.BasePageResponse;
import com.vueblog.webapi.response.BaseResponse;
import com.vueblog.webapi.response.BlogInfoResponse;
import com.vueblog.webapi.service.IBlogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vueblog.webapi.utils.MarkdownUtils;
import org.apache.ibatis.javassist.NotFoundException;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.thymeleaf.expression.Maps;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author luosj
 * @since 2021-05-15
 */
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, BlogEntity> implements IBlogService {

    @Autowired
    private BlogMapper blogMapper;

    @Autowired
    private BlogTagsMapper blogTagsMapper;

    /**
     * 分页查询博客
     * @param request
     * @return
     */
    @Override
    public BasePageResponse getBlogInfoPageList(GetBlogInfoPageRequest request) {
        Page<HashMap<String, Object>> page = new Page<>(request.getPageNum(), request.getPageSize());
        List<HashMap<String, Object>> pageList = blogMapper.getBlogInfoPageList(page, request);
        page.setRecords(pageList);
        return new BasePageResponse<>(ResponseEnum.SUCCESS, (int) page.getTotal(), page.getRecords());
    }

    /**
     * 获取发布且推荐博客
     */
    @Override
    public BaseResponse getPublishedAndRecommendBlogList() {
        List<HashMap<String, Object>> list = blogMapper.getPublishedAndRecommendBlogList();
        return new BaseResponse(ResponseEnum.SUCCESS,list);
    }

    /**
     * 根据博客id获取博客
     */
    @Transactional
    @Override
    public BaseResponse getBlogByid(Long id) {
        System.out.println(id);
        BlogInfoResponse entity = blogMapper.getBlogByid(id);
        if (entity == null) {
            throw new BusinessException("该博客不存在");
        }
        String content = entity.getContent();
        BlogEntity updateEntity = new BlogEntity();
        updateEntity
                .setId(id)
                .setViews(entity.getViews() + 1);
        entity.setContent(MarkdownUtils.markdownToHtml(content));
        // 文章访问数量自增1
        blogMapper.updateById(updateEntity);
        return new BaseResponse(ResponseEnum.SUCCESS,entity);
    }

    /**
     * 根据分类id获取博客
     */
    @Transactional
    @Override
    public BasePageResponse getBlogByTypeId(BasePageRequest request,  Long id) {
        Page<BlogInfoResponse> page = new Page<>(request.getPageNum(), request.getPageSize());
        List<BlogInfoResponse> pageList = blogMapper.getBlogByTypeId(page, id);
        return new BasePageResponse<>(ResponseEnum.SUCCESS, (int) page.getTotal(), pageList);
    }

    /**
     * 根据标签id获取博客
     */
    @Transactional
    @Override
    public BasePageResponse getBlogByTagId(BasePageRequest request,  Long id) {
        Page<BlogInfoResponse> page = new Page<>(request.getPageNum(), request.getPageSize());
        List<BlogInfoResponse> pageList = blogMapper.getBlogByTagId(page, id);
        return new BasePageResponse<>(ResponseEnum.SUCCESS, (int) page.getTotal(), pageList);
    }

    /**
     * 博客归档
     */
    @Override
    public BaseResponse archiveBlog() {
        List<String> years = blogMapper.findGroupYear();
        Map<String, List<BlogEntity>> archiveBlogs = new HashMap<>();
        for (String year : years) {
            archiveBlogs.put(year, blogMapper.findByYear(year));
        }
        // 获取博客总数
        Integer blogCount = blogMapper.selectCount(new QueryWrapper<BlogEntity>().lambda()
                .eq(BlogEntity::getPublished, true));
        // 设置返回的归档信息
        ArchiveBlogResponse archiveBlogResponse = new ArchiveBlogResponse();
        archiveBlogResponse
                .setArchiveBlogs(archiveBlogs)
                .setBlogCount(blogCount);
        return new BaseResponse(ResponseEnum.SUCCESS, archiveBlogResponse);
    }

    /**
     * 根据map的key排序
     *
     * @param map 待排序的map
     * @param isDesc 是否降序，true：降序，false：升序
     */
    public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, V> map, boolean isDesc) {
        Map<K, V> result = new HashMap<>();
        if (isDesc) {
            map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey().reversed())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        } else {
            map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        }
        return result;
    }

    /**
     * 创建博客
     * @param request
     * @return
     */
    @Override
    @Transactional
    public BaseResponse createBlog(CreateOrUpdateBlogRequest request) {
        // 设置博客实体类的基本信息
        BlogEntity blogEntity = setBlogBaseInfo(request);
        if (blogMapper.createBlog(blogEntity) > 0) { // 判断博客是否添加成功
            // 创建博客标签中间表的关联信息
            createBlogTag(blogEntity.getId(), request.getTagId());
            // 返回成功信息
            return new BaseResponse(ResponseEnum.SUCCESS);
        }else {
            // 返回失败信息
            return new BaseResponse(ResponseEnum.DATABASE_ERROR);
        }
    }

    @Transactional
    void createBlogTag(Long blogId, List<Long> tagId) {
        if (tagId.size() != 0) {
            for (Long tid : tagId) {
                blogTagsMapper.insert(new BlogTagsEntity(blogId, tid));
            }
        }
    }

    // 设置博客信息
    @Transactional
    BlogEntity setBlogBaseInfo(CreateOrUpdateBlogRequest request) {
        checkTitleBeforeCreate(request);
        UserEntity user =(UserEntity) SecurityUtils.getSubject().getPrincipal();
        BlogEntity blogEntity = new BlogEntity();
        blogEntity
                .setFlag(request.getFlag())
                .setTitle(request.getTitle())
                .setContent(request.getContent())
                .setTypeId(request.getTypeId())
                .setFirstPicture(request.getFirstPicture())
                .setDescription(request.getDescription())
                .setRecommend(request.getRecommend())
                .setShareStatement(request.getShareStatement())
                .setAppreciation(request.getAppreciation())
                .setCommentabled(request.getCommentabled())
                .setPublished(request.getPublished())
                .setUserId(user.getId())
                .setCreateTime(LocalDateTime.now())
                .setUpdateTime(blogEntity.getCreateTime())
                .setViews(8);
        return blogEntity;
    }

    // 创建博客前检查标题是否已存在
    @Transactional
    void checkTitleBeforeCreate(CreateOrUpdateBlogRequest request) {
        Integer count = blogMapper.selectCount(new QueryWrapper<BlogEntity>().lambda()
                .eq(BlogEntity::getTitle, request.getTitle()));
        if (count > 0) {
            throw new BusinessException("该标题已存在");
        }
    }

    /**
     * 编辑博客
     */
    @Override
    @Transactional
    public BaseResponse updateBlogInfo(CreateOrUpdateBlogRequest request, String id) {
        // 更新前检查博客是否已存在并设置博客实体类的基本信息
        BlogEntity entity = beforeUpdate(request, id);
        if (blogMapper.updateById(entity) > 0) {// 判断博客是否修改成功
            // 更新博客标签中间表的关联信息
            updateBlogTag(entity.getId(), request.getTagId());
            // 返回成功信息
            return new BaseResponse(ResponseEnum.SUCCESS);
        }else {
            // 返回失败信息
            return new BaseResponse(ResponseEnum.DATABASE_ERROR);
        }
    }

    // 更新博客标签中间表
    @Transactional
    void updateBlogTag(Long blogId, List<Long> tagId) {
        blogTagsMapper.delete(new QueryWrapper<BlogTagsEntity>().lambda()
                .eq(BlogTagsEntity::getBlogsId, blogId));
        if (tagId.size() != 0) {
            for (Long tid : tagId) {
                blogTagsMapper.insert(new BlogTagsEntity(blogId, tid));
            }
        }
    }

    // 更新前的检查和设置
    @Transactional
    BlogEntity beforeUpdate(CreateOrUpdateBlogRequest request, String id) {
        BlogEntity entity = blogMapper.selectById(id);
        if ( entity == null){
            throw new BusinessException("该博客不存在");
        }
        int count = this.count(new QueryWrapper<BlogEntity>().lambda()
                .eq(BlogEntity::getTitle, request.getTitle())
                .ne(BlogEntity::getId, id));
        if (count > 0) {
            throw new BusinessException("该标题已存在");
        }else {
            UserEntity user =(UserEntity) SecurityUtils.getSubject().getPrincipal();
            entity
                    .setFlag(request.getFlag())
                    .setTitle(request.getTitle())
                    .setContent(request.getContent())
                    .setTypeId(request.getTypeId())
                    .setFirstPicture(request.getFirstPicture())
                    .setDescription(request.getDescription())
                    .setRecommend(request.getRecommend())
                    .setShareStatement(request.getShareStatement())
                    .setAppreciation(request.getAppreciation())
                    .setCommentabled(request.getCommentabled())
                    .setPublished(request.getPublished())
                    .setUserId(user.getId())
                    .setUpdateTime(LocalDateTime.now());
        }
        return entity;
    }

    /**
     * 删除博客
     */
    @Transactional
    @Override
    public BaseResponse deleteBlogInfo(String id) {
        // 删除博客标签中间表的关联信息
        deleteBlogTag(id);
        // 删除博客
        int result = blogMapper.deleteById(id);
        if (result > 0) {// 判断博客是否删除成功
            // 返回成功信息
            return new BaseResponse(ResponseEnum.SUCCESS);
        }
        // 返回失败信息
        return new BaseResponse(ResponseEnum.ERROR);
    }

    @Transactional
    void deleteBlogTag(String id) {
        blogTagsMapper.delete(new QueryWrapper<BlogTagsEntity>().lambda()
                .eq(BlogTagsEntity::getBlogsId, id));
    }

    /**
     * 根据关键字获取博客
     */
    @Override
    public BasePageResponse getBlogByWord(GetBlogInfoByWordRequest request) {
        Page<HashMap<String, Object>> page = new Page<>(request.getPageNum(), request.getPageSize());
        List<HashMap<String, Object>> pageList = blogMapper.getBlogByWord(page, request);
        page.setRecords(pageList);
        return new BasePageResponse<>(ResponseEnum.SUCCESS, (int) page.getTotal(), page.getRecords());
    }
}
